package org.sapling.data.dao.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;
import org.sapling.common.utils.data.ResultSetUtil;
import org.sapling.data.beans.MetadataFieldTemplate;
import org.sapling.data.beans.MetadataTemplate;
import org.sapling.data.beans.TableConfig;
import org.sapling.data.config.DataSourceConfig;
import org.sapling.data.dao.DataCatchRepository;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

/**
 * 
* @ClassName: DataRepositoryImpl  
* @Description: 数据缓存配置实现类
* @author DcfZero 
* @date 2020年5月31日  
*
 */
@Component
public class DataCatchRepositoryImpl implements DataCatchRepository{
	private static final Logger log = org.slf4j.LoggerFactory.getLogger(DataCatchRepositoryImpl.class);
	
	@Autowired
	private HashMap<String, JdbcTemplate> dataSourceRepository;
	
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	//已注册数据表
	private final ConcurrentHashMap<String, TableConfig> tableStored = new ConcurrentHashMap();

	//字典仓库
	private final ConcurrentHashMap<String, Map<String,String>> dictStored = new ConcurrentHashMap();

	//元数据表
	private final ConcurrentHashMap<String,MetadataTemplate> metadataStored = new ConcurrentHashMap();
	
	@Override
	public void init() {
		init(true);
	}
	
	/**
	 * 数据缓存初始化
	* @Title: init  
	* @param checkVersion
	* @return void  返回类型  
	* @throws
	 */
	private void init(boolean checkVersion) {
		this.tableStored.clear();
		ArrayList<String> dictTableList = new ArrayList<String>();
		this.jdbcTemplate.query("SELECT * FROM sys_table", rs -> {
			String tableId = rs.getString("table_id");
			String isDict = rs.getString("is_dict");
			this.tableStored.put(tableId, new TableConfig(ResultSetUtil.toMap(rs)));
			if(!StringUtils.isEmpty(isDict) && isDict.equalsIgnoreCase("Y")) {
				dictTableList.add(tableId);
			}
		});
		initDict(dictTableList);
	}
	
	/**
	 * 
	* @Title: initDict  
	* @param dictTableList
	* @return void  返回类型  
	* @throws
	 */
	private void initDict(ArrayList<String> dictTableList) {
		log.info("<<------开始解析字典表------>>");
		for(String dictTable : dictTableList) {
			TableConfig config = tableStored.get(dictTable);
			// id,pid,key,value
			String[] dictConfig = config.getDictConfig().split(",");
			if(dictConfig.length != 5) {
				log.info("<<" + dictTable + ">>" +"字典配置无法解析");
				continue;
			}else {
				log.info("<<" + dictTable + ">>" +"字典已创建");
				dictStored.put(dictTable, new ConcurrentHashMap<String, String>());
			}
		}
		log.info("<<------解析字典表完成------>>");
		initDict4MetaData();
	}
	
	/**
	 * 
	* @Title: initDict4MetaData  
	* @return void  返回类型  
	* @throws
	 */
	private void initDict4MetaData() {
		log.info("<<------开始解析元数据------>>");
		List<MetadataFieldTemplate> translateFields = new ArrayList<MetadataFieldTemplate>();
		this.jdbcTemplate.query(MetadataTemplate.getQueryString(), rs -> {
			MetadataTemplate template;
			MetadataFieldTemplate field;
			String tableId = rs.getString("table_id");
			if(!this.metadataStored.containsKey(tableId)) {
				template = new MetadataTemplate(ResultSetUtil.toMap(rs));
				this.metadataStored.put(tableId, template);
				field = template.getFieldList().get(0);
			}else {
				template = this.metadataStored.get(tableId);
				field = template.setField(ResultSetUtil.toMap(rs));
			}
			String dictTableId = field.getFieldDict();
			String tableLimit = field.getFieldDictLimit();
			if(!StringUtils.isEmpty(dictTableId) && !dictTableId.equals("null")) {	
				if(!dictStored.containsKey(dictTableId)) {
					log.info("<<" + dictTableId + ">>" +"未找到匹配的字典项");
				}else {
					translateFields.add(field);
				}
			}
		});
		initTransFields(translateFields);
		log.info("<<------解析元数据完毕------>>");
	}

	
	/**  
	* @Title: initTransFields  
	* @param translateFields
	* @return void  返回类型  
	* @throws  
	*/ 
	private void initTransFields(List<MetadataFieldTemplate> translateFields) {
		for(MetadataFieldTemplate field : translateFields) {
			String dictTableId = field.getFieldDict();
			String tableLimit = field.getFieldDictLimit();
			tableLimit = tableLimit.replace('[', '`');
			tableLimit = tableLimit.replace(']', '`');
			
			String tableName = tableStored.get(dictTableId).getTableName();
			String dictConfig = tableStored.get(dictTableId).getDictConfig();
			
			Map<String,String> dictMap = dictStored.get(dictTableId);
			JdbcTemplate dictJdbcTemplate = dataSourceRepository.get(tableStored.get(dictTableId).getConnectId());
			
			String[] limits = dictConfig.split(",");
			String id = limits[0];
			String pid = limits[1];
			String key = limits[2];
			String value = limits[3];
			String seq = limits[4];
			StringBuffer queryString = new StringBuffer();
			queryString.append("SELECT").append(" * ").append(" FROM ").append(tableName).append(" WHERE ").append(tableLimit);
			try {
				dictJdbcTemplate.query(queryString.toString(), res -> {
					String curKey = res.getString(key);
					if(dictMap.containsKey(curKey)) {
						return;
					}
					String curValue = res.getString(value);
					log.info("添加字典" + curKey + "=>" + curValue);
					dictMap.put(curKey,curValue);
					String curId = res.getString(id);
					String limit = "`" + pid + "`" + " = " + curId;
					findAllNodes(dictJdbcTemplate,dictMap,id,pid,key,value,limit,seq,tableName);
				});
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	private void findAllNodes(JdbcTemplate template,Map<String,String> dictMap,String id,String pid,String key,String value,String tableLimit,String seq,String tableName) {
		StringBuffer queryString = new StringBuffer();
		queryString.append("SELECT").append(" * ").append(" FROM ").append(tableName).append(" WHERE ").append(tableLimit).append(" ORDER BY ").append(seq);
		try {
			List<Map<String,Object>> queryLists = template.queryForList(queryString.toString());
			if(queryLists.size() == 0) {
				return;
			}else {
				for(Map<String,Object> row : queryLists) {
					String curKey = row.get(key).toString();
					if(dictMap.containsKey(curKey)) {
						continue;
					}
					String curId = row.get(id).toString();
					String curValue = row.get(value).toString();
					dictMap.put(curKey,curValue);
					log.info("添加字典" + curKey + "=>" + curValue);
					tableLimit = "`" + pid + "`" + " = " + curId;
					findAllNodes(template,dictMap,id,pid,key,value,tableLimit,seq,tableName);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/** 
	* @param tableId
	* @return 
	* @see org.sapling.data.dao.DataCatchRepository#getDict(java.lang.String) 
	*/
	@Override
	public Map<String, String> getDict(String tableId) {
		return dictStored.get(tableId);
	}

	/** 
	* @param tableId
	* @return 
	* @see org.sapling.data.dao.DataCatchRepository#getMetadataTemplate(java.lang.String) 
	*/
	@Override
	public MetadataTemplate getMetadataTemplate(String tableId) {
		return metadataStored.get(tableId);
	}

	/** 
	* @param tableId
	* @return 
	* @see org.sapling.data.dao.DataCatchRepository#getTableConnectId(java.lang.String) 
	*/
	@Override
	public String getTableConnectId(String tableId) {
		return tableStored.get(tableId).getConnectId();
	}

	
}
